#include "reg51.h"
#include "intrins.h"

#define FOSC            11059200UL
#define BRT             (65536 - FOSC /57600/4)


#define SI_CLK0_CONTROL	16			// Register definitions

#define SI_SYNTH_PLL_A	26
#define SI_SYNTH_MS_0		42
#define SI_SYNTH_MS_1		50
#define SI_SYNTH_MS_2		58
#define SI_PLL_RESET		177

#define SI_R_DIV_1		0x00			// R-division ratio definitions
#define SI_R_DIV_2		0b00010000
#define SI_R_DIV_4		0b00100000
#define SI_R_DIV_8		0b00110000
#define SI_R_DIV_16		0b01000000
#define SI_R_DIV_32		0b01010000
#define SI_R_DIV_64		0b01100000
#define SI_R_DIV_128	0b01110000

#define SI_CLK_SRC_PLL_A	0x00
#define SI_CLK_SRC_PLL_B	0b00100000
#define SI5351_XTAL_FREQ 	25000000			// Crystal frequency
#define SI5351_PLL_INPUT_SOURCE   15
#define SI5351_OUTPUT_ENABLE_CTRL 3
#define SI5351_BUS_BASE_ADDW 0xC0
#define SI5351_BUS_BASE_ADDR 0xC1
#define SI5351_DEVICE_STATUS            0
#define SI5351_CRYSTAL_LOAD             183
#define SI5351_CRYSTAL_LOAD_MASK        (3<<6)
#define SI5351_CRYSTAL_LOAD_0PF         (0<<6)
#define SI5351_CRYSTAL_LOAD_6PF         0x40
#define SI5351_CRYSTAL_LOAD_8PF         0x80
#define SI5351_CRYSTAL_LOAD_10PF        0xc0


#define I2CCFG          (*(unsigned char volatile xdata *)0xfe80)
#define I2CMSCR         (*(unsigned char volatile xdata *)0xfe81)
#define I2CMSST         (*(unsigned char volatile xdata *)0xfe82)
#define I2CSLCR         (*(unsigned char volatile xdata *)0xfe83)
#define I2CSLST         (*(unsigned char volatile xdata *)0xfe84)
#define I2CSLADR        (*(unsigned char volatile xdata *)0xfe85)
#define I2CTXD          (*(unsigned char volatile xdata *)0xfe86)
#define I2CRXD          (*(unsigned char volatile xdata *)0xfe87)

typedef unsigned char uint8_t;
typedef unsigned int uint16_t;
typedef unsigned long uint32_t;
typedef long   int32_t;



sfr     AUXR       =   0x8e;
sfr     T2H        =   0xd6;
sfr     T2L        =   0xd7;
sfr     P1M1			 =   0x91;
sfr     P1M0			 =   0x92;
sfr     P3M1			 =   0xb1;
sfr     P3M0			 =   0xb2;
sfr     P_SW1       =   0xa2;
sfr     P_SW2       =   0xba;

sfr     ADC_CONTR   =   0xbc;
sfr     ADC_RES     =   0xbd;
sfr     ADC_RESL    =   0xbe;
sfr     ADCCFG      =   0xde;

sbit    P11=P1^1;
sbit    P16=P1^6;
sbit    P17=P1^7;
sbit    P35=P3^5;
sbit    P36=P3^6;
sbit    P37=P3^7;

sbit    SDA         =   P3^3;
sbit    SCL         =   P3^2;

bit busy;

unsigned char inchar=0x00;
unsigned char inString[21]="";

unsigned char anttenuator=0x00;
unsigned char sensorValue[2];
int point_num;
uint32_t  startFreq ;
uint32_t  stopFreq  ;
uint32_t freqstep = 1;


//---------------------I2C-------------------

void Delay(int t)
{
    int i;

    for (i=0; i<t; i++)
    {
        _nop_();

    }
}

void Start()
{
		  SCL=1;
		  SDA=1;
	   Delay(8);
			SDA=0;
	   Delay(8);
		  SCL=0;
}

void Stop()
{		  
	    SCL=1;
			SDA=0;
	    Delay(8);
		  SCL=0;
	    Delay(8);
		  SCL=1;
		  SDA=1;
}


void SendData(unsigned char dat) 
{
	unsigned char i; 
	
	for(i=0;i<8;i++)
	{
		SCL=0;
		Delay(8);
		if((dat&0x80)==0)
			SDA=0;
		else
		  SDA=1;

		SCL=1;
		Delay(8);
		dat=dat<<1;
		
	}

}

void RecvACK()
{
SCL=0;
Delay(8);
SDA=1;
SCL=1;
Delay(20);	
SCL=0;
Delay(8);		
}


//---------------Si5351---------------------
/*uint8_t si5351_read(uint8_t addr)
{
	uint8_t reg_val = 0;
	Start(); 
	SendData(SI5351_BUS_BASE_ADDW);      //
	RecvACK();
	SendData(addr);     //
	RecvACK();
	Stop();    
	
	Start(); 
	SendData(SI5351_BUS_BASE_ADDR);      //
	RecvACK();
	reg_val = RecvData(); 
	SendACK();
  Stop(); 
	
	return reg_val;
		
}*/

void si5351_write(uint8_t addr, uint8_t dat)
{
	Start(); 
	SendData(SI5351_BUS_BASE_ADDW);      //
	RecvACK();
	SendData(addr);     //
	RecvACK();
	SendData(dat);     //
	RecvACK();
	Stop();              
}



void setupPLL(uint8_t pll, uint8_t mult, uint32_t num, uint32_t denom)
{
  uint32_t P1;					// PLL config register P1
  uint32_t P2;					// PLL config register P2
  uint32_t P3;					// PLL config register P3

  P1 = (uint32_t)(128 * ((float)num / (float)denom));
  P1 = (uint32_t)(128 * (uint32_t)(mult) + P1 - 512);
  P2 = (uint32_t)(128 * ((float)num / (float)denom));
  P2 = (uint32_t)(128 * num - denom * P2);
  P3 = denom;

  si5351_write(pll + 0, (P3 & 0x0000FF00) >> 8);
  si5351_write(pll + 1, (P3 & 0x000000FF));
  si5351_write(pll + 2, (P1 & 0x00030000) >> 16);
  si5351_write(pll + 3, (P1 & 0x0000FF00) >> 8);
  si5351_write(pll + 4, (P1 & 0x000000FF));
  si5351_write(pll + 5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16));
  si5351_write(pll + 6, (P2 & 0x0000FF00) >> 8);
  si5351_write(pll + 7, (P2 & 0x000000FF));
}

void setupMultisynth(uint8_t synth,uint32_t divider,uint8_t rDiv)
{
  uint32_t P1;					// Synth config register P1
  uint32_t P2;					// Synth config register P2
  uint32_t P3;					// Synth config register P3

  P1 = 128 * divider - 512;
  P2 = 0;							// P2 = 0, P3 = 1 forces an integer value for the divider
  P3 = 1;

  si5351_write(synth + 0,   (P3 & 0x0000FF00) >> 8);
  si5351_write(synth + 1,   (P3 & 0x000000FF));
  si5351_write(synth + 2,   ((P1 & 0x00030000) >> 16) | rDiv);
  si5351_write(synth + 3,   (P1 & 0x0000FF00) >> 8);
  si5351_write(synth + 4,   (P1 & 0x000000FF));
  si5351_write(synth + 5,   ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16));
  si5351_write(synth + 6,   (P2 & 0x0000FF00) >> 8);
  si5351_write(synth + 7,   (P2 & 0x000000FF));
}

void si5351aSetFrequency(uint32_t frequency )
{
  uint32_t pllFreq;
  uint32_t xtalFreq = SI5351_XTAL_FREQ ;// Crystal frequency
  uint32_t l;
  float f;
  uint8_t mult;
  uint32_t num;
  uint32_t denom;
  uint32_t divider;

  divider = 900000000 / frequency;// Calculate the division ratio. 900,000,000 is the maximum internal 
                                                                  // PLL frequency: 900MHz
  if (divider % 2) divider--;		// Ensure an even integer division ratio

  pllFreq = divider * frequency;	// Calculate the pllFrequency: the divider * desired output frequency

  mult = pllFreq / xtalFreq;		// Determine the multiplier to get to the required pllFrequency
  l = pllFreq % xtalFreq;			// It has three parts:
  f = l;							// mult is an integer that must be in the range 15..90
  f *= 1048575;					// num and denom are the fractional parts, the numerator and denominator
  f /= xtalFreq;					// each is 20 bits (range 0..1048575)
  num = f;						// the actual multiplier is  mult + num / denom
  denom = 1048575;				// For simplicity we set the denominator to the maximum 1048575
  // Set up PLL A with the calculated multiplication ratio
  setupPLL(SI_SYNTH_PLL_A, mult, num, denom);
                                                                  // Set up MultiSynth divider 0, with the calculated divider. 
                                                                  // The final R division stage can divide by a power of two, from 1..128. 
                                                                  // reprented by constants SI_R_DIV1 to SI_R_DIV128 (see si5351a.h header file)
                                                                  // If you want to output frequencies below 1MHz, you have to use the 
                                                                  // final R division stage

   setupMultisynth(SI_SYNTH_MS_0,divider,SI_R_DIV_1);
                                                                  // Reset the PLL. This causes a glitch in the output. For small changes to 
                                                                  // the parameters, you don't need to reset the PLL, and there is no glitch
   //si5351_write(SI_PLL_RESET,0xA0);	
                                                                  // Finally switch on the CLK0 output (0x4F)
                                                                  // and set the MultiSynth0 input to be PLL A
   si5351_write(SI_CLK0_CONTROL, 0x4F|SI_CLK_SRC_PLL_A);
   
	 si5351_write(SI5351_OUTPUT_ENABLE_CTRL, 0xfe); //only enable clk0 output

}

void si5351_init()
{

	  si5351_write(SI5351_PLL_INPUT_SOURCE, 0x00);
	  si5351_write(SI5351_CRYSTAL_LOAD, 0x92);

}




//---------------UART---------------------

void UartIsr() interrupt 4
{

    if (TI)
    {
        TI = 0;
        busy = 0;
			  
    }
    if (RI)
    {
      RI = 0;
			inchar=SBUF;
    }

}

void UartInit()
{
    SCON = 0x50;
    T2L = BRT;
    T2H = BRT >> 8;
    AUXR = 0x15;
    busy = 0;
}

unsigned char readchar()
{
	unsigned char temp;
  ES = 0;
	while(RI==0);
	temp=SBUF;
	ES = 1;
	return temp;
	
}
void UartSend(unsigned char dat)
{
    while (busy);
    busy = 1;
    SBUF = dat;
}



void main()
{
	
	int i;

	P1M0=0xc2;
	P1M1=0x01;
	P3M0=0x00;
	P3M1=0x00;
	P17=0;
	P16=0;
	P11=0;
  P_SW1 =0x00;       //RXD/P3.0, TXD/P3.1
  P_SW2 = 0x30;       //SCL_4/P3.2, SDA_4/P3.3
	
	
	ADCCFG = 0x2f;    //set ADC clock =sysclock/2
	ADC_CONTR = 0x80;	//enable ADC module

    UartInit();
    ES = 1;
    EA = 1;
    si5351_init();
    
    while (1)
    {
		
    switch(inchar){
    case 'v': inchar=0; UartSend(145);break;
		case 's': 
    {
			inchar=0;
      UartSend(145);
      UartSend(anttenuator);//b2 20dB ,b1 20dB, b0 10dB
      UartSend(66);
      UartSend(67);
      break;
      }
		case 'm': 
    {
			inchar=0;
      
			ADC_CONTR |= 0x40;
			_nop_();
      _nop_();
			while (!(ADC_CONTR & 0x20)); 
			ADC_CONTR &= ~0x20;   
			sensorValue[0] = ADC_RES&0x03;  //high 2bit
			sensorValue[1] = ADC_RESL; //low 8bit
			
      UartSend(sensorValue[1]); //send low-bit first
			UartSend(sensorValue[0]); //then send hig-bit 
      UartSend(0);
      UartSend(0);

		  break;
    }
		
		case 'r': 
    {
			inchar=0;
      anttenuator=readchar();
			P16=(anttenuator&0x01)?1:0;
			P17=((anttenuator&0x02)>>1)?1:0;
      P11=((anttenuator&0x04)>>2)?1:0;
      break;
    }

		case 'x': 
    {
      inchar=0;
		  for(i=0;i<21;i++)
		     inString[i]=readchar();
  
      startFreq = (inString[0]-0x30)*100000000+(inString[1]-0x30)*10000000+(inString[2]-0x30)*1000000+(inString[3]-0x30)*100000+(inString[4]-0x30)*10000+(inString[5]-0x30)*1000+(inString[6]-0x30)*100+(inString[7]-0x30)*10+inString[8]-0x30;
      freqstep= (inString[9]-0x30)*10000000+(inString[10]-0x30)*1000000+(inString[11]-0x30)*100000+(inString[12]-0x30)*10000+(inString[13]-0x30)*1000+(inString[14]-0x30)*100+(inString[15]-0x30)*10+inString[16]-0x30;
      
      point_num=((inString[20]-0x30)+(inString[19]-0x30)*10+(inString[18]-0x30)*100+(inString[17]-0x30)*1000);
		
     for (i=0;i<point_num;i++)
        { 
				si5351aSetFrequency(startFreq+freqstep*i);
					
				ADC_CONTR |= 0x40;
				_nop_();
				_nop_();
				while (!(ADC_CONTR & 0x20)); 
				ADC_CONTR &= ~0x20;   
				sensorValue[0] = ADC_RES&0x03;  //high 2bit
				sensorValue[1] = ADC_RESL; //low 8bit
				UartSend(sensorValue[1]); //send low-bit first
				UartSend(sensorValue[0]); //then send hig-bit 
        UartSend(0x00);//channel 2 no use
        UartSend(0x00);//channel 2 no use
          }
      break;
    }
		
		case 'f': 
		  inchar=0;
		 for(i=0;i<9;i++)
		     inString[i]=readchar();
     startFreq = (inString[0]-0x30)*100000000+(inString[1]-0x30)*10000000+(inString[2]-0x30)*1000000+(inString[3]-0x30)*100000+(inString[4]-0x30)*10000+(inString[5]-0x30)*1000+(inString[6]-0x30)*100+(inString[7]-0x30)*10+inString[8]-0x30;
		 si5351aSetFrequency(startFreq);
      break;
     
		} //end switch
		
		//inchar=0;
	

    }// end while
}

